/* 
* Pounce Announce
*/

#include <sourcemod>
#include <l4d_stocks>

#include "macros.sp"
#include "helpers.sp"

//globals
new Handle:hMaxPounceDistance;
new Handle:hMinPounceDistance;
new Handle:hMaxPounceDamage;
//hunter position store
new Float:infectedPosition[32][3]; //support up to 32 slots on a server
//cvars
new Handle:hMinPounceAnnounce;

new String:best_pounce_name[64];
new Float:best_pounce_damage;
new best_pounce_index;

new bool:first_round = true;
new bool:show_summary = false;

#define DEBUG 0

//For variable types of pounce display
enum PounceDistanceDisplay
{
	None = 0, 
	Units = 1, 
	UnitsAndFeet = 2,
	UnitsAndMeters = 3,
	Feet = 4,
	Meters = 5
}

public Plugin:myinfo = 
{
	name = "Pounce Announce",
	author = "n0limit",
	description = "Announces hunter pounces to the entire server",
	version = "1.5",
	url = "http://forums.alliedmods.net/showthread.php?t=93605"
}

public OnPluginStart()
{
	hMaxPounceDistance = FindConVar("z_pounce_damage_range_max");
	hMinPounceDistance = FindConVar("z_pounce_damage_range_min");
	hMaxPounceDamage = FindConVar("z_hunter_max_pounce_bonus_damage");
	hMinPounceAnnounce = CreateConVar("pounceannounce_minimum","0","The minimum amount of damage required to announce the pounce", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_NOTIFY);
	
	AutoExecConfig(true,"pounceannounce");
	
	HookEvent("lunge_pounce",Event_PlayerPounced);
	HookEvent("ability_use",Event_AbilityUse);
	HookEvent("round_end", event_round_end);
	HookEvent("round_start", event_round_start);
}

public OnMapEnd()
{
	first_round = true;
	show_summary = false;
}

public event_round_start(Handle:event, const String:name[], bool:dontBroadcast)
{
	if(first_round) // 1st round
	{
		first_round = false;		
		show_summary = false;
	}
	else //2nd round
	{
		show_summary = true;
		first_round = true;
	}

}
public event_round_end(Handle:event, const String:name[], bool:dontBroadcast)
{
	
		if(show_summary && best_pounce_damage > 0.0) //2nd round
		{	
			/* display in green for winner and yellow to other*/
			if(IsValidClient(best_pounce_index))
			{
				decl String:check_name[64];
				GetClientName(best_pounce_index, check_name, sizeof(check_name));

				/* the winner is connected */
				if(strcmp(check_name, best_pounce_name) == 0)
				{
					PrintToChat(best_pounce_index, "\x01Best \x05Hunter pounce\x01 : \x05%s\x01 with \x05%.01f\x01 damages", best_pounce_name, best_pounce_damage);
					PrintToChatAllExclude(best_pounce_index, -1, "\x01Best \x04Hunter pounce\x01 : \x04%s\x01 with \x04%.01f\x01 damages", best_pounce_name, best_pounce_damage);	
				}
				else //the winner has left, print yellow for everyone
				{
					PrintToChatAll("\x01Best \x04Hunter pounce\x01 : \x04%s\x01 with \x04%.01f\x01 damages", best_pounce_name, best_pounce_damage);	
				}
			}
			else //should not happen, but in case, print to all in yellow if client became invalid
			{
				PrintToChatAll("\x01Best \x04Hunter pounce\x01 : \x04%s\x01 with \x04%.01f\x01 damages", best_pounce_name, best_pounce_damage);
			}

			best_pounce_damage = 0.0;
			best_pounce_index = 0;
			strcopy(best_pounce_name, sizeof(best_pounce_name), "Nobody");
		}

		show_summary = false;
}

public Event_AbilityUse(Handle:event, const String:name[], bool:dontBroadcast)
{
	new user = GetClientOfUserId(GetEventInt(event, "userid"));
	
	//Save the location of the player who just used an infected ability
	GetClientAbsOrigin(user,infectedPosition[user]);	
}

public Event_PlayerPounced(Handle:event, const String:name[], bool:dontBroadcast)
{
	new Float:pouncePosition[3];
	new attackerId = GetEventInt(event, "userid");
	new victimId = GetEventInt(event, "victim");
	new attackerClient = GetClientOfUserId(attackerId);
	new victimClient = GetClientOfUserId(victimId);
	new minAnnounce = GetConVarInt(hMinPounceAnnounce);
	
	if(!IsValidInfected(attackerClient))
		return;

	if(!IsValidSurvivor(victimClient))
		return;

	//get hunter-related pounce cvars
	new max = GetConVarInt(hMaxPounceDistance);
	new min = GetConVarInt(hMinPounceDistance);
	new maxDmg = GetConVarInt(hMaxPounceDamage);
	
	//Get current position while pounced
	GetClientAbsOrigin(attackerClient,pouncePosition);
	
	//Calculate 2d distance between previous position and pounce position
	new distance = RoundToNearest(GetVectorDistance(infectedPosition[attackerClient], pouncePosition));
	
	//Get damage using hunter damage formula
	//damage in this is expressed as a float because my server has competitive hunter pouncing where the decimal counts
	new Float:dmg = (((distance - float(min)) / float(max - min)) * float(maxDmg)) + 1;
	
	if(dmg > best_pounce_damage)
	{
		best_pounce_damage = dmg;
		GetClientName(attackerClient, best_pounce_name, sizeof(best_pounce_name));
		best_pounce_index = attackerClient;
	}
	if(distance >= min && dmg >= minAnnounce)
	{
		PrintToChatAllExclude(attackerClient, victimClient, "\x04%N\x01 pounced \x04%N\x01 for \x04%.01f damage\x01 over %.0f meters",attackerClient,victimClient,dmg,distance * 0.0213);
		PrintToChatOnly(attackerClient, victimClient, "\x05%N\x01 pounced \x05%N\x01 for \x05%.01f damage\x01 over %.0f meters",attackerClient,victimClient,dmg,distance * 0.0213);		
	}
}
